home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------------------
-
- File: Exceptions.h
- Desc: Exception handling mechanism & macros for C++ (and C)
-
- Michael C. Greenspon, Integral Information Systems, Berkeley, CA
- (415) 524-5200; Alink: INTEGRAL; Internet: mcg@violet.berkeley.edu
-
- Based on original by Andrew Shebanow (original version by Andy Heninger)
- of Apple Macintosh Developer Technical Support
-
- Portions Copyright © 1989-1990 Apple Computer, Inc.
- All rights reserved.
-
- See original as distributed with sample code #14 for theory of operation
-
- ------------------------------------------------------------------------------------------*/
-
- #ifndef __EXCEPTIONS__
- #define __EXCEPTIONS__
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __SETJMP__
- #include <SetJmp.h>
- #endif
-
- // In the MacApp kit...
- #include "UFailure.h"
-
- #ifdef __cplusplus
- extern "C" {
- #endif
- // Since we eat the error code and message that the MacApp failure unit
- // passes us, we need to store them someplace where your failure
- // handling code can get at it. We use global variables (keen, eh?).
- extern long gFailMessage; // Current failure message
- extern short gFailError; // Current failure error
-
- pascal void StandardHandler(short e, long m, void* Handler_StaticLink);
- #ifdef __cplusplus
- };
- #endif
-
- // 6 Mar 91 mcg
- //
- // Hah! Just a little macro tweaking here and now we can write:
- //
- // try {
- // stuff that might throw an exception;
- // }
- // catch {
- // do stuff to recover;
- // break; // exit handler, recovered
- // }
- //
- //
- // Or:
- //
- // try something;
- // catch break;
- //
- // which recovers from all exceptions without further checking.
- // Falling through the bottom of the catch (without doing a break or goto)
- // signals the next handler up the chain by calling Failure() again.
- //
- // Also you can do a break in a try block which just falls out of the try
- // The catch is only executed by something in the try throwing an exception
- //
- // So now this follows C structuring syntax and is also closer in syntax to
- // proposed C++ exception handling mechanisms
- //
- // errata: you can only have one try...catch pair per block. If you want more than
- // one, enclose the pair in its own block. But try is often within a block (if, while)
- // anyway, so not really a big deal. Nesting try/catch pairs within try/catch blocks
- // is no prob and often useful.
- //
- // Never allow your destructors to throw exceptions. Period.
- //
- // And, obviously, there must be a catch for every try...
- //
- // Be careful not to declare auto objects that require destruction within a try block.
- // If you get an exception, the autos will be out of scope in the catch but no one will
- // have called the destructor. Be sure to destroy other autos (eg., those with function
- // scope) explicitly within the catch block by calling their destructors before throwing
- // to the next handler. Syntax is obj.Class::~Class(); in the MPW 3.1 version of CFront,
- // you must specify the Class:: qualifier, so this doesn't work polymorphically.
- // This is a deficiency in CFront as compared with C++ ARM which specifies obj.~Class()
- // as a valid virtual call syntax.
- //
- // Also watch out for macro expansions in constructors with CFront 1.0. It has been
- // known to screw up on occasion. Look at the C code if you're having problems.
- //
- // MPW C does a very good job of optimizing out the loops, making the generated code
- // comparable to the previous versions.
- //
-
-
- #define try \
- jmp_buf errorBuf; \
- if (! setjmp(errorBuf) ) { \
- FailInfo fi; \
- CatchFailures(&fi, StandardHandler, errorBuf); \
- do { \
-
- #define catch \
- } while (0); \
- Success(&fi); \
- } \
- else \
- for(; (1); Failure(gFailError, gFailMessage))
-
-
- /*
- The default MacApp/Object Pascal semantics are that returning from
- an error handler will go to the next failure handler on the
- stack. The way we do this in C++ is that we call failure
- again with the same error information. We can use a goto (break) out
- of the catch block to stop the error processing.
- */
-
- // Should go in UFailure.h
-
- #ifdef __cplusplus
- inline void FailInit(Boolean t) { if (t) Failure(memFullErr,0); }
- #else
- #define FailInit(t) { if (t) Failure(memFullErr,0); }
- #endif
-
-
- #endif
-